import fs from 'fs/promises'
import path from 'path'
import { v4 as uuidv4 } from 'uuid'
import { processFile, checkFileType} from '../utils/fileProcessors/index.js'
import logger from './logger.js'
import { vectorStore } from './vectorStore.js'
import { TextChunker } from '../utils/textChunker.js'
import { modelService } from './model.js'

/**
 * 文档服务
 */
export class DocumentService {
  constructor() {
    this.documentsDir = path.join(process.cwd(), 'data/documents')
  }

  /**
   * 初始化文档目录
   */
  async init() {
    try {
      await fs.mkdir(this.documentsDir, { recursive: true })
      logger.info('Documents directory initialized')
    } catch (error) {
      logger.error('Failed to initialize documents directory:', error)
      throw error
    }
  }

  /**
   * 获取所有文档
   */
  async getAllDocuments() {
    try {
      await this.init()
      
      const files = await fs.readdir(this.documentsDir)
      const metaFiles = files.filter(file => file.endsWith('.meta.json'))
      
      const documents = []
      for (const metaFile of metaFiles) {
        try {
          const content = await fs.readFile(path.join(this.documentsDir, metaFile), 'utf-8')
          const doc = JSON.parse(content)
          documents.push(doc)
        } catch (error) {
          logger.warn(`Failed to read document metadata: ${metaFile}`, error)
        }
      }
      
      return documents.sort((a, b) => {
        return new Date(b.uploadTime) - new Date(a.uploadTime)
      })
    } catch (error) {
      logger.error('Failed to get all documents:', error)
      throw error
    }
  }

  /**
   * 获取文档详情
   */
  async getDocument(id) {
    try {
      const metaPath = path.join(this.documentsDir, `${id}.meta.json`)
      const content = await fs.readFile(metaPath, 'utf-8')
      return JSON.parse(content)
    } catch (error) {
      logger.error(`Failed to get document: ${id}`, error)
      throw error
    }
  }

  /**
   * 上传文档
   */
  async uploadDocument(file, options = {}) {
    try {
      await this.init()
      
      // 检查文件类型
      const { valid, type } = checkFileType(file.originalname)
      if (!valid) {
        throw new Error(`Unsupported file type: ${type}`)
      }
      
      // 生成文档ID
      const id = uuidv4()
      
      // 保存文件
      const filePath = path.join(this.documentsDir, id)
      await fs.writeFile(filePath, file.buffer)
      
      // 创建元数据
      const meta = {
        id,
        title: options.title || file.originalname,
        originalName: file.originalname,
        type,
        size: file.size,
        uploadTime: new Date().toISOString(),
        status: 'pending'
      }
      
      // 保存元数据
      const metaPath = path.join(this.documentsDir, `${id}.meta.json`)
      await fs.writeFile(metaPath, JSON.stringify(meta, null, 2), 'utf-8')
      
      return meta
    } catch (error) {
      logger.error('Failed to upload document:', error)
      throw error
    }
  }

  /**
   * 删除文档
   */
  async deleteDocument(id) {
    try {
      // 删除文件
      const filePath = path.join(this.documentsDir, id)
      const metaPath = path.join(this.documentsDir, `${id}.meta.json`)
      
      // 读取元数据
      let meta
      try {
        const content = await fs.readFile(metaPath, 'utf-8')
        meta = JSON.parse(content)
      } catch (error) {
        logger.warn(`Document metadata not found: ${id}`)
      }
      
      // 删除向量
      if (meta && meta.status === 'vectorized') {
        await vectorStore.deleteVectors(`parent_id == "${id}"`)
      }
      
      // 删除文件和元数据
      await Promise.all([
        fs.unlink(filePath).catch(err => logger.warn(`Failed to delete document file: ${id}`, err)),
        fs.unlink(metaPath).catch(err => logger.warn(`Failed to delete document metadata: ${id}`, err))
      ])
      
      return { id }
    } catch (error) {
      logger.error(`Failed to delete document: ${id}`, error)
      throw error
    }
  }

  /**
   * 向量化文档
   */
  async vectorizeDocument(id, options = {}) {
    try {
      // 读取文档
      const filePath = path.join(this.documentsDir, id)
      const metaPath = path.join(this.documentsDir, `${id}.meta.json`)
      
      // 读取元数据
      const metaContent = await fs.readFile(metaPath, 'utf-8')
      const meta = JSON.parse(metaContent)
      
      // 清理已存在的向量
      await vectorStore.deleteVectors(`parent_id == "${id}"`)
      
      // 处理文档内容
      const content = await processFile(filePath)
      
      // 分段
      const chunkSize = options.chunkSize || 1000
      const overlap = options.overlap || 200
      const chunks = TextChunker.splitText(content, { chunkSize, overlap })
      
      // 生成向量
      const vectors = []
      for (let i = 0; i < chunks.length; i++) {
        const chunk = chunks[i]
        const embedding = await modelService.generateEmbedding(chunk.content)
        
        vectors.push({
          id: `${id}_${i}`,
          parent_id: id,
          content: chunk.content,
          title: meta.title,
          chunk_index: i,
          embedding
        })
      }
      
      // 存储向量
      await vectorStore.insertVectors(vectors)
      
      // 更新元数据
      meta.status = 'vectorized'
      meta.vectorizedAt = new Date().toISOString()
      meta.chunksCount = chunks.length
      await fs.writeFile(metaPath, JSON.stringify(meta, null, 2), 'utf-8')
      
      return {
        id,
        chunksCount: chunks.length
      }
    } catch (error) {
      logger.error(`Failed to vectorize document: ${id}`, error)
      throw error
    }
  }
}

export const documentService = new DocumentService() 